#!/bin/sh -x
# $1 = assembly source, $2 = instr file to save to and use, $3 csr file to save to and use

REGEX_ARITH_INSTR="^\ *[\ 0-9a-f]+\ (add|sub|sll|slt|xor|srl|sra|or|and|nop|li|mv|not|neg|[zs]ext|[zs]eq?z|sltz|sgtz|lla)"
REGEX_BRANCH_INSTR="^\ *[\ 0-9a-f]+\ b"
REGEX_JUMP_INSTR="^\ *[\ 0-9a-f]+\ (lui|auipc|jal|j|jr|ret|call|tail)"
REGEX_LOADSTORE_INSTR="^\ *[\ 0-9a-f]+\ (lb|lh|lw|ld|sb|sh|sw|sd)"
REGEX_SYS_INSTR="^\ *[\ 0-9a-f]+\ (e(call|break)|fence)"
REGEX_M_EXT="^\ *[\ 0-9a-f]+\ (mul|div|rem)"
REGEX_A_EXT="^\ *[\ 0-9a-f]+\ (lr\.|sc\.|amo)"
REGEX_F_EXT="^\ *[\ 0-9a-f]+\ (feq|fl|fs|fm|fn|fa|fs|fd|fc|fr)"
REGEX_C_EXT="^\ *[\ 0-9a-f]+\ c\."
REGEX_ZICSR_EXT="^\ *[\ 0-9a-f]+\ c[^\.]"
REGEX_ZIFENCEI_EXT="^\ *[\ 0-9a-f]+\ fence\.i"
REGEX_COUNTERS_EXT="^\ *[\ 0-9a-f]+\ (rdcycle|rdtime|rdinstret)"
REGEX_MMODE_INSTR="^\ *[\ 0-9a-f]+\ (mret|wfi)"
REGEX_SMODE_INSTR="^\ *[\ 0-9a-f]+\ (sfence\.|sinval\.|sret)"
REGEX_HMODE_INSTR="^\ *[\ 0-9a-f]+\ (hfence\.|hinval\.|hlv\.|hsv\.)"

# extract csr instructions
awk '{ $1=""; $2=""; print; }' "$1" | sed 's/^ *//' | grep ^csr | "$(dirname "$(realpath "$0")")/filter_csr_reg.py" | sort | uniq -c | sort -h > "$3"
# grep filtering step to reduce amount of false positive (hex addresses)
tail -n +7 "$1" | awk 'NF=3 { print $3 }' | grep -v -E "^\ *([0-9abcdef]{4}|[0-9abcdef]{8}|unimp|section|\.[24]?byte|[\<\>]\:)" | awk 'NF' | sort | uniq -c | sort -h > "$2"

# unprivileged spec instructions
# filter base integer instruction set instructions
grep -v -E "$REGEX_M_EXT" "$2" \
    | grep -v -E "$REGEX_A_EXT" \
    | grep -v -E "$REGEX_F_EXT" \
    | grep -v -E "$REGEX_C_EXT" \
    | grep -v -E "$REGEX_ZICSR_EXT" \
    | grep -v -E "$REGEX_ZIFENCEI_EXT" \
    | grep -v -E "$REGEX_COUNTERS_EXT" \
    | grep -v -E "$REGEX_MMODE_INSTR" \
    | grep -v -E "$REGEX_SMODE_INSTR" \
    | grep -v -E "$REGEX_HMODE_INSTR" \
    | tee "$2".base
# filter arith instructions
grep -E "$REGEX_ARITH_INSTR" "$2" | tee "$2".arith
# filter branch instructions
grep -E "$REGEX_BRANCH_INSTR" "$2" | tee "$2".branch
# filter jump instructions
grep -E "$REGEX_JUMP_INSTR" "$2" | tee "$2".jump
# filter loadstore instructions
grep -E "$REGEX_LOADSTORE_INSTR" "$2" | tee "$2".loadstore
# filter env instructions (need to exclude fence.i)
grep -E "$REGEX_SYS_INSTR" "$2" | grep -v -E "$REGEX_ZIFENCEI_EXT" | tee "$2".sys

# filter m ext instructionm ext instructions
grep -E "$REGEX_M_EXT" "$2" | tee "$2".m
# filter a ext instructions
grep -E "$REGEX_A_EXT" "$2" | tee "$2".a
# filter f ext instructions
grep -E "$REGEX_F_EXT" "$2" | tee "$2".f
# filter c ext instructions
grep -E "$REGEX_C_EXT" "$2" | tee "$2".c
# filter zicsr ext instructions
grep -E "$REGEX_ZICSR_EXT" "$2" | tee "$2".zicsr
# filter zifencei ext instructions
grep -E "$REGEX_ZIFENCEI_EXT" "$2" | tee "$2".zifencei
# filter counters ext instructions
grep -E "$REGEX_COUNTERS_EXT" "$2" | tee "$2".counters

# privileged spec instructions
# filter m mode priv instructions
grep -E "$REGEX_MMODE_INSTR" "$2" | tee "$2".mmode
# filter s mode instructions
grep -E "$REGEX_SMODE_INSTR" "$2" | tee "$2".smode
# filter h mode instructions
grep -E "$REGEX_HMODE_INSTR" "$2" | tee "$2".hmode
